package com.have.blog.admin.service.impl;

import com.github.pagehelper.PageHelper;
import com.have.blog.admin.constant.AdminBlogConstant;
import com.have.blog.admin.constant.AdminMessageConstant;
import com.have.blog.admin.domain.dto.ResourceMenuDto;
import com.have.blog.admin.redis.ResourceMenuCacheService;
import com.have.blog.admin.service.AdminResourceMenuService;
import com.have.blog.base.enums.AdminMenuEnum;
import com.have.blog.base.enums.BlogStatus;
import com.have.blog.base.wrapper.Wrapper;
import com.have.blog.model.mapper.ResourceMenuMapper;
import com.have.blog.model.models.ResourceMenu;
import com.have.blog.model.models.ResourceMenuExample;
import com.have.blog.utils.MyBeanUtils;
import com.have.blog.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@SuppressWarnings("all")
public class AdminResourceMenuServiceImpl implements AdminResourceMenuService {

    @Autowired
    private ResourceMenuMapper resourceMenuMapper;

    @Autowired
    private ResourceMenuCacheService resourceMenuCacheService;

    @Override
    public List<ResourceMenuDto> getList(ResourceMenuDto categoryMenuDto) {
        Map<String, Object> resultMap = new HashMap<>();
        PageHelper.startPage(categoryMenuDto.getPageNum(), categoryMenuDto.getPageSize());
        ResourceMenuExample example = new ResourceMenuExample();
        ResourceMenuExample.Criteria criteria = example.createCriteria();
        if (!StringUtils.isEmpty(categoryMenuDto.getKeyword()) && !StringUtils.isEmpty(categoryMenuDto.getKeyword().trim())) {
            criteria.andNameLike("%" + categoryMenuDto.getKeyword() + "%");
        }
        if (categoryMenuDto.getMenuLevel() != 0) {
            criteria.andMenuLevelEqualTo(categoryMenuDto.getMenuLevel());
        }
        List<ResourceMenu> list = resourceMenuMapper.selectByExample(example);
        List<ResourceMenuDto> resultList = MyBeanUtils.copyListProperties(list, ResourceMenuDto::new);
        List<Integer> uidList = new ArrayList<>();
        resultList.forEach(item -> {
            if (item.getParentUid() != null) {
                uidList.add(item.getParentUid());
            }
        });

        if (!CollectionUtils.isEmpty(uidList)) {
            ResourceMenuExample example1 = new ResourceMenuExample();
            example1.createCriteria()
                    .andUidIn(uidList);
            List<ResourceMenu> parents = resourceMenuMapper.selectByExample(example1);
            List<ResourceMenuDto> parentList = MyBeanUtils.copyListProperties(parents, ResourceMenuDto::new);
            Map<Integer, ResourceMenuDto> map = new HashMap<>();
            parentList.forEach(item -> {
                map.put(item.getUid(), item);
            });
            resultList.forEach( item -> {
                item.setParentResourceMenu(map.get(item.getParentUid()));
            });
        }
        return resultList;
    }

    @Override
    public List<ResourceMenuDto> getHierarchyList() {
        List<ResourceMenuDto> hierarchyList = resourceMenuCacheService.getHierarchyList();
        if (hierarchyList != null) {
            return hierarchyList;
        }
        List<ResourceMenu> firsts = getAllFirstResourceMenu();
        List<ResourceMenuDto> firstRsourceMenus = MyBeanUtils.copyListProperties(firsts, ResourceMenuDto::new);
        // 查询二级菜单
        List<ResourceMenu> seconds = getChildCategoryMenu(firsts);
        List<ResourceMenuDto> secondResourceMenu = MyBeanUtils.copyListProperties(seconds, ResourceMenuDto::new);
        // 获取三级按钮
        List<ResourceMenu> thirds = getChildCategoryMenu(seconds);
        List<ResourceMenuDto> thirdResourceMenu = MyBeanUtils.copyListProperties(thirds, ResourceMenuDto::new);

        Map<Integer, List<ResourceMenuDto>> map = new HashMap<>();
        // 给二级菜单设置三级按钮
        thirdResourceMenu.forEach(item -> {
            if (item.getParentUid() != null) {
                List<ResourceMenuDto> tempList = map.get(item.getParentUid());
                if (tempList == null) {
                    tempList = new ArrayList<ResourceMenuDto>();
                    map.put(item.getParentUid(), tempList);
                }
                tempList.add(item);
            }
        });
        secondResourceMenu.forEach(item -> {
            List<ResourceMenuDto> tempList = map.get(item.getUid());
            item.setChildResourceMenu(tempList);
        });

        // 给一级菜单设置二级菜单
        map.clear();
        secondResourceMenu.forEach(item -> {
            List<ResourceMenuDto> tempList = map.get(item.getParentUid());
            if (tempList == null) {
                tempList = new ArrayList<>();
                map.put(item.getParentUid(), tempList);
            }
            tempList.add(item);
        });
        for (ResourceMenuDto parentItem : firstRsourceMenus) {
            parentItem.setChildResourceMenu(map.get(parentItem.getUid()));
        }
        resourceMenuCacheService.setHierarchyList(firstRsourceMenus);
        return firstRsourceMenus;
    }

    @Override
    public List<ResourceMenuDto> getAllButton() {
        List<ResourceMenuDto> buttonsWitParent = resourceMenuCacheService.getButtonsWitParent();
        if (buttonsWitParent != null) {
            return buttonsWitParent;
        }
        ResourceMenuExample example = new ResourceMenuExample();
        ResourceMenuExample.Criteria criteria = example.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andMenuLevelEqualTo(2);
        example.setOrderByClause("sort desc");
        List<ResourceMenu> seconds = resourceMenuMapper.selectByExample(example);
        List<ResourceMenu> buttons = getChildCategoryMenu(seconds);
        List<ResourceMenuDto> resultList = MyBeanUtils.copyListProperties(seconds, ResourceMenuDto::new);
        List<ResourceMenuDto> buttonList = MyBeanUtils.copyListProperties(buttons, ResourceMenuDto::new);

        Map<Integer, List<ResourceMenuDto>> map = new HashMap<>();
        buttonList.forEach(item -> {
            List<ResourceMenuDto> tempList = map.get(item.getParentUid());
            if (tempList == null) {
                tempList = new ArrayList<>();
                map.put(item.getParentUid(), tempList);
            }
            tempList.add(item);
        });
        // 给二级菜单设置三级按钮
        resultList.forEach(item -> {
            item.setChildResourceMenu(map.get(item.getUid()));
        });
        // 过滤没有子按钮的二级菜单
        resultList = resultList.stream().filter(item -> {
            return item.getChildResourceMenu() != null;
        }).collect(Collectors.toList());
        resourceMenuCacheService.setButtonsWithParent(resultList);
        return resultList;
    }

    public List<ResourceMenu> getAllFirstResourceMenu() {
        ResourceMenuExample example = new ResourceMenuExample();
        example.createCriteria()
                .andMenuLevelEqualTo(1)
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andMenuTypeEqualTo(AdminMenuEnum.MENU.getType());
        example.setOrderByClause("sort desc");
        List<ResourceMenu> list = resourceMenuMapper.selectByExample(example);
        return list;
    }

    public List<ResourceMenu> getChildCategoryMenu(List<ResourceMenu> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<Integer> uids = new ArrayList<>();
        list.forEach(item -> {
                uids.add(item.getUid());
        });
        ResourceMenuExample childExample = new ResourceMenuExample();
        childExample.createCriteria()
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus())
                .andParentUidIn(uids);
        childExample.setOrderByClause("sort desc");
        List<ResourceMenu> childList = resourceMenuMapper.selectByExample(childExample);
        return childList;
    }


    @Override
    public Wrapper addResourceMenu(ResourceMenuDto categoryMenuDto) {
        if (categoryMenuDto.getMenuLevel() == AdminBlogConstant.ONE) {
            categoryMenuDto.setParentUid(null);
        }
        ResourceMenu categoryMenu = new ResourceMenu();
        MyBeanUtils.copyProperties(categoryMenuDto, categoryMenu);
        int insert = resourceMenuMapper.insertSelective(categoryMenu);
        if (insert > 0) {
            resourceMenuCacheService.delHierarchyList();
            resourceMenuCacheService.delButtons();
            return Wrapper.successWithMessage(AdminMessageConstant.INSERT_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.INSERT_FAIL);
    }

    @Override
    public Wrapper editResourceMenu(ResourceMenuDto categoryMenuDto) {
        ResourceMenu categoryMenu = resourceMenuMapper.selectByPrimaryKey(categoryMenuDto.getUid());
        categoryMenu.setName(categoryMenuDto.getName());
        categoryMenu.setMenuLevel(categoryMenuDto.getMenuLevel());
        categoryMenu.setParentUid(categoryMenuDto.getParentUid());
        categoryMenu.setSummary(categoryMenuDto.getSummary());
        categoryMenu.setIcon(categoryMenuDto.getIcon());
        categoryMenu.setIsJumpExternalUrl(categoryMenuDto.getIsJumpExternalUrl());
        categoryMenu.setUrl(categoryMenuDto.getUrl());
        categoryMenu.setIsShow(categoryMenuDto.getIsShow());
        categoryMenu.setSort(categoryMenuDto.getSort());
        categoryMenu.setMenuType(categoryMenuDto.getMenuType());
        int update = resourceMenuMapper.updateByPrimaryKeySelective(categoryMenu);
        if (update > 0) {
            resourceMenuCacheService.delHierarchyList();
            resourceMenuCacheService.delButtons();

            return Wrapper.successWithMessage(AdminMessageConstant.UPDATE_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.UPDATE_FAIL);
    }

    @Override
    public Wrapper stickResourceMenu(ResourceMenuDto categoryMenuDto) {
        ResourceMenu categoryMenu = resourceMenuMapper.selectByPrimaryKey(categoryMenuDto.getUid());
        ResourceMenuExample example = new ResourceMenuExample();
        ResourceMenuExample.Criteria criteria = example.createCriteria();
        if (categoryMenu.getMenuLevel() == 2 || categoryMenu.getMenuType() == AdminMenuEnum.BUTTON.getType()) {
            criteria.andParentUidEqualTo(categoryMenu.getParentUid());
        }
        criteria.andMenuLevelEqualTo(categoryMenu.getMenuLevel());
        example.setOrderByClause("sort desc");
        List<ResourceMenu> list = resourceMenuMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return Wrapper.success();
        }
        ResourceMenu top = list.get(0);
        categoryMenu.setSort(top.getSort() + 1);
        int update = resourceMenuMapper.updateByPrimaryKeySelective(categoryMenu);
        if (update > 0) {
            return Wrapper.success();
        }
        return  Wrapper.failed();
    }

    @Override
    public Wrapper deleteResourceMenu(ResourceMenuDto categoryMenuDto) {
        ResourceMenuExample example = new ResourceMenuExample();
        example.createCriteria()
                .andParentUidEqualTo(categoryMenuDto.getUid())
                .andStatusEqualTo(BlogStatus.ENABLE.getStatus());
        long count = resourceMenuMapper.countByExample(example);
        if (count > 0) { // 如果此菜单下还有子菜单不允删除
            return Wrapper.failed(AdminMessageConstant.CHILDREN_MENU_UNDER_THIS_MENU);
        }
        ResourceMenu categoryMenu = new ResourceMenu();
        categoryMenu.setUid(categoryMenuDto.getUid());
        categoryMenu.setStatus(BlogStatus.DISABLE.getStatus());
        int delete = resourceMenuMapper.updateByPrimaryKeySelective(categoryMenu);
        if (delete > 0) {
            resourceMenuCacheService.delHierarchyList();
            resourceMenuCacheService.delButtons();
            return Wrapper.successWithMessage(AdminMessageConstant.DELETE_SUCCESS);
        }
        return Wrapper.failed(AdminMessageConstant.DELETE_FAIL);
    }

    @Override
    public List<ResourceMenu> getAll() {
        List<ResourceMenu> resourceMenus = resourceMenuMapper.selectByExample(new ResourceMenuExample());
        return resourceMenus;
    }
}
